import {isEmpty, isFunction, isNumber, isString, trim} from 'lodash-es';
import dayjs, {Dayjs} from 'dayjs'
import utc from "dayjs/plugin/utc";
import weekday from 'dayjs/plugin/weekday';
import localeData from 'dayjs/plugin/localeData';
import weekOfYear from 'dayjs/plugin/weekOfYear';
import weekYear from 'dayjs/plugin/weekYear';
import advancedFormat from 'dayjs/plugin/advancedFormat';
import customParseFormat from "dayjs/plugin/customParseFormat";

dayjs.extend(customParseFormat);
dayjs.extend(advancedFormat);
dayjs.extend(weekday);
dayjs.extend(localeData);
dayjs.extend(weekOfYear);
dayjs.extend(weekYear);
dayjs.extend(utc);
dayjs.extend(function (o, c) {
    // todo support Wo (ISO week)
    var proto = c.prototype;
    var oldFormat = proto.format;

    proto.format = function f(formatStr) {
        var str = (formatStr || '').replace('Wo', 'wo');
        return oldFormat.bind(this)(str);
    };
});

/**
 * 当前系统的 日期格式
 * @type {string}
 */
export const curDateFormat = 'YYYY-MM-DD';
export const curDatetimeFormat = 'YYYY-MM-DD HH:mm:ss';

/**
 * 获取支持输入的日期格式，一般用于设置 DatePicker 组件的 format 属性
 * @returns {string[]}
 */
export const getDateFormats = () => (['YYYY-MM-DD', 'YYYY/MM/DD', 'YYYYMMDD', 'YYYY-M-D', 'YYYY/M/D']);

/**
 * 触发 DatePicker 组件的 Click 事件，以弹出日期选择浮层，并获得输入焦点
 * @param e Event
 * @deprecated
 */
export const triggerDateClick = (e: any) => {
    if (e && e.currentTarget) {
        let isFirst = e.currentTarget.getAttribute('isfirst');

        if ('1' !== isFirst) {
            e.currentTarget.setAttribute('isfirst', '1');

            if (e.currentTarget.childNodes && e.currentTarget.childNodes[0] &&
                e.currentTarget.childNodes[0].childNodes && e.currentTarget.childNodes[0].childNodes[0]) {
                e.currentTarget.childNodes[0].childNodes[0].click();
            }
        }

    }
};

function formatCn(cn: string) {
    return window.localUtils && window.localUtils.formatMsgByCn ? window.localUtils.formatMsgByCn(cn) : cn;
}

/**
 * 根据开始和结束期间，回显对应的中文
 * @param beginPeriod
 * @param endPeriod
 * @returns {string}
 */
// @ts-ignore
export const previewPeriod = (beginPeriod?, endPeriod?) => {
    let isEn = 'en-US' === window.localStorage.getItem('umi_locale');

    if (beginPeriod && endPeriod) {

        if (beginPeriod.name) {

            if (isEmpty(endPeriod.name)) {
                return isEn ? `From ${beginPeriod.name} to now` : `${beginPeriod.name} 至今`;

            } else if (endPeriod.name === beginPeriod.name) {
                return beginPeriod.name;

            } else {
                return isEn ? `From ${beginPeriod.name} to ${endPeriod.name}` : `${beginPeriod.name} 至 ${endPeriod.name}`;
            }

        } else if (endPeriod.name) {
            return isEn ? `${endPeriod.name} and before` : `${endPeriod.name} 及之前`;

        } else {
            return formatCn('全部');
        }
    } else {
        return formatCn('全部');
    }
};

/**
 * new 一个日期实例（dayjs 实例）
 * @param date {string | number | Date | Dayjs}
 * @param option {{ locale?: string, format?: string, utc?: boolean } | string | string[]}
 * @param locale {string}
 */
export function newDateIns(date?: dayjs.ConfigType, option?: dayjs.OptionType, locale?: string) {
    let tempDate = date;
    if (isNumber(tempDate) && tempDate > 0 && tempDate <= 9999999999) {
        tempDate = tempDate * 1000;

    } else if(tempDate === null || tempDate === undefined) {
        // 如果 date 是空值，则取当前时区的当前时间戳
        tempDate = getTimezoneTimestamp() * 1000;
    }
    // @ts-ignore
    return dayjs(tempDate, option, locale);
}

/**
 * 判断 srcDate 是否为 Dayjs 实例
 * @param srcDate any 待判断的参数
 */
export function isDateIns(srcDate: any) {
    return srcDate && isFunction(srcDate.format);
}

/**
 * 将 srcDate 从 srcFormat 格式转成 distFormat 格式
 * @param srcDate string 当前时区的日期字符串
 * @param srcFormat string srcDate 的日期格式。默认：'YYYY-MM-DD HH:mm:ss'
 * @param distFormat string 日期格式。默认: 'YYYY-MM-DD'
 */
export function changeDateFormat(srcDate: string, srcFormat = 'YYYY-MM-DD HH:mm:ss', distFormat = 'YYYY-MM-DD') {
    let date = dayjs(srcDate, 'YYYY-MM-DD HH:mm:ss');

    if (date.isValid()) {
        return myFormatTime(dateStr2Timestamp(srcDate, srcFormat), distFormat);
    } else {
        return '';
    }
}

/**
 * 将 GMT0 时区的时间戳（value），转成当前时区的时间戳
 * @param value {number} GMT0 时区的时间戳
 */
export function gmt0ToCurrentTimestamp(value: number) {

    if(isNumber(value)) {
        let tzTimestamp = getTimezone() * 3600000;
        let tstamp = value;
        // 转成毫秒
        if (tstamp > 0 && tstamp <= 9999999999) {
            tstamp = tstamp * 1000;
        }
        return Math.floor((tstamp + tzTimestamp) / 1000);
    } else {
        return 0;
    }
}

/**
 * 将系统时间戳，转成 GMT0 时区的时间戳
 * @param value {number} 系统时间戳
 */
export function sysTimestampToGmt0(value: number) {

    if(isNumber(value)) {
        let tzTimestamp = getSystemTimezone() * 3600000;
        let tstamp = value;
        // 转成毫秒
        if (tstamp > 0 && tstamp <= 9999999999) {
            tstamp = tstamp * 1000;
        }
        return Math.floor((tstamp - tzTimestamp) / 1000);
    } else {
        return 0;
    }
}


/**
 * 获取当前时区的当前时间戳
 */
export function getTimezoneTimestamp() {
    let gmt0Ts = sysTimestampToGmt0(new Date().getTime());
    let curTs = getTimezone() * 3600;
    return gmt0Ts + curTs;
}

/**
 * 日期字符串转为时间戳(GMT0 时区)
 * @param srcDate 系统时区的日期字符串或 dayjs 实例。例如：'2020-04-02 12:12:12'
 * @param format 日期格式。例如：'YYYY-MM-DD HH:mm:ss'
 * @return number GMT0 时区的时间戳
 */
export function dateStr2Timestamp(srcDate: dayjs.ConfigType, format?: string) {

    if (isNumber(srcDate)) return srcDate;

    let systemTzTimestamp = getSystemTimezone() * 3600000;
    let reVal = dayjs.utc(srcDate, format).valueOf() - systemTzTimestamp;

    // if (isString(srcDate)) {
    //     // let tzTimestamp = getTimezone() * 3600000;
    //     // reVal = dayjs.utc(srcDate, format).valueOf() - tzTimestamp;
    // } else {
    //     reVal = dayjs.utc(srcDate, format).valueOf();
    // }

    return reVal <= 9999999999 ? reVal : Math.floor(reVal / 1000);
}

/**
 * 将 srcDate 转出 format 日期格式
 * @param timestamp string | number | Dayjs 待转换的日期。如果是时间戳，则必须是 GMT0 时区的时间戳
 * @param format string 日期格式。默认：'YYYY-MM-DD HH:mm:ss'
 * @return string 当前用户时区的日期字符串
 */
export const myFormatTime = function (timestamp?: string | number | Dayjs, format = '') {
    let tempDate;
    let tzTimestamp = getTimezone() * 3600000;
    let tstamp = timestamp;

    if (tstamp) {

        // 如果不是时间戳，则转成 GMT0 时区的时间戳
        if (!isNumber(tstamp)) {
            tstamp = dateStr2Timestamp(tstamp);
        }

    } else {
        // 转成 GMT0 时区的时间戳
        tstamp = dateStr2Timestamp(new Date());
    }

    // 转成毫秒
    if (tstamp > 0 && tstamp <= 9999999999) {
        tstamp = tstamp * 1000;
    }

    if (null == format || '' == trim(format)) {
        format = 'YYYY-MM-DD HH:mm:ss';
    }
    let tmpTimestamp = tstamp + tzTimestamp;
    // console.log('new Date(tmpTimestamp)', new Date(tmpTimestamp));
    // console.log('dayjs(new Date(tmpTimestamp)).format(format)', dayjs(new Date(tmpTimestamp)).format(format));
    // tempDate = new Date(tstamp + tzTimestamp);
    // return dayjs.utc(tempDate).format(format);
    return dayjs(new Date(tmpTimestamp)).format(format);
};

export function fixedZero(val: number) {
    return val * 1 < 10 ? `0${val}` : val;
}

/**
 * 获取时区；优先级： 缓存的时区 window.localStorage.getItem('TIMEZONE') > 系统时区
 */
export function getTimezone() {
    let sysTimezone = getSystemTimezone();
    let timezoneStr = window.localStorage.getItem('TIMEZONE');

    if (isString(timezoneStr)) {
        let tz = parseInt(timezoneStr.replace('GMT', ''));

        if (isNumber(tz)) return tz;
        else return sysTimezone;

    } else {
        return sysTimezone;
    }
}

/**
 * 获取当前系统的时区
 */
export function getSystemTimezone() {
    return 0 - new Date().getTimezoneOffset() / 60;
}

/**
 * 日期转周数
 * date2Week('2020-11-2')
 * @param str
 */
export function date2Week(str: string) {

    // 获取date，不传则默认为当前date，这里没有做时间格式校验
    let d = str ? new Date(str) : new Date();

    // start为1/1对应的date【0时0分】
    let start: any = new Date(d.getFullYear() + '/01/01');

    // end 为当前date【0时0分】
    let end: any = new Date(d.toLocaleDateString());

    // 天数差 【上面的0时0分意在避免影响天数的计算】
    let dayOffset = (end - start) / 1000 / 60 / 60 / 24;

    // 以周一为一周起点，故而需要加上元旦时的偏移量
    let base = dayOffset + start.getDay();
    return (
        dayOffset ? base / 7 > 52 ? dayOffset % 7 + start.getDay() ? 1 : 52 : Math.ceil(base / 7) : 1
    );
}